#region << 版 本 注 释 >>
/*----------------------------------------------------------------
 * 版权所有 (c) 2025   保留所有权利。
 * CLR版本：4.0.30319.42000
 * 机器名称：DESKTOP-GLJ2Q8J
 * 公司名称：
 * 命名空间：AutoCAD.EntityTools.RegistryManage
 * 唯一标识：d319dfd9-36ae-43d3-ace2-62780c9782ba
 * 文件名：AutoCadRegistry
 * 当前用户域：DESKTOP-GLJ2Q8J
 * 
 * 创建者： Guo_79991
 * 电子邮箱：xxxx@hotmail.com
 * 创建时间：2025/9/1 18:40:01
 * 版本：V1.0.0
 * 描述：
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/
#endregion << 版 本 注 释 >>

using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security;
using System.Web;

namespace AutoCAD.EntityTools.RegistryManage
{
    /// <summary>
    /// Cad注册表工具类
    /// </summary>
    public class AutoCadRegistry
    {
        /// <summary>
        /// 版本关系对照字典
        /// </summary>
        private IReadOnlyDictionary<string, string> VersionRelationship { get; set; } = GetVersionText();

        /// <summary>
        /// 获取版本对照表
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        private static IReadOnlyDictionary<string, string> GetVersionText()
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();
            string path = "Versions.txt";
            if (!File.Exists(path))
            {
                throw new Exception("版本文件不存在");
            }
            var versions = File.ReadAllLines(path);
            foreach (var version in versions)
            {
                var str = version.Split(',');
                if (!dict.ContainsKey(str[0]))
                {
                    dict.Add(str[0], str[1]);
                }
            }

            return dict;
        }


        /// <summary>
        /// 获得64位版本
        /// </summary>
        /// <returns></returns>
        private string[] Get64Versions()
        {
            RegistryKey keyLocalMachine = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
            RegistryKey keyAutoCAD = keyLocalMachine.OpenSubKey("SOFTWARE\\Autodesk\\Hardcopy");
            if (keyAutoCAD is null) return new string[] { };
            var versions = keyAutoCAD.GetValueNames();
            return versions;
        }
        /// <summary>
        /// 获得32位版本
        /// </summary>
        /// <returns></returns>
        private string[] Get32Versions()
        {
            RegistryKey keyLocalMachine = Autodesk.AutoCAD.Runtime.Registry.LocalMachine;
            RegistryKey keyAutoCAD = keyLocalMachine.OpenSubKey("SOFTWARE\\Autodesk\\Hardcopy");
            if (keyAutoCAD is null) return new string[] { };
            var versions = keyAutoCAD.GetSubKeyNames();
            return versions;
        }

        /// <summary>
        /// 获得Cad版本
        /// </summary>
        /// <param name="versions"></param>
        /// <param name="bitType"></param>
        /// <returns></returns>
        private List<AutoCadVersion> GetAcadVersions(string[] versions, BitType bitType)
        {
            List<AutoCadVersion> cadVersions = new List<AutoCadVersion>();
            foreach (var version in versions)
            {
                var str = version.Split('\\');
                var versionStr = str[str.Length - 2];
                if (VersionRelationship.ContainsKey(versionStr))
                {
                    AutoCadVersion autoCadVersion = new AutoCadVersion();
                    autoCadVersion.RegistryPath = version;
                    autoCadVersion.RegistryVersion = versionStr;
                    autoCadVersion.VersionName = VersionRelationship[versionStr];
                    autoCadVersion.BitVersion = bitType;
                    cadVersions.Add(autoCadVersion);
                }
            }

            return cadVersions;
        }

        /// <summary>
        /// 获得Cad版本,包含32位和64位
        /// </summary>
        /// <returns></returns>
        public List<AutoCadVersion> GetVersions()
        {
            List<AutoCadVersion> autoCadVersions = new List<AutoCadVersion>();
            var version64s = Get64Versions();
            var version32s = Get32Versions();
            autoCadVersions.AddRange(GetAcadVersions(version64s, BitType.bit64));
            autoCadVersions.AddRange(GetAcadVersions(version32s, BitType.bit32));
            return autoCadVersions;
        }

        /// <summary>
        /// 注册安装注册表
        /// </summary>
        /// <param name="dirname">创建的文件名称</param>
        /// <param name="version">版本信息</param>
        /// <param name="desc">描述信息</param>
        /// <param name="dllpath">dll路径</param>
        /// <exception cref="Exception"></exception>
        /// <summary>
        /// 注册安装注册表（带权限处理）
        /// </summary>
        private bool InstallRegistry(string dirname, string desc, string dllpath, AutoCadVersion autoCadVersion)
        {
            RegistryKey applications = null;
            RegistryKey myProgram = null;

            try
            {
                applications = GetApplication(autoCadVersion);

                if (applications == null)
                {
                    throw new Exception("无法访问Applications注册表项");
                }

                // 检查是否有写权限
                if (!HasWriteAccess(applications))
                {
                    throw new UnauthorizedAccessException("程序没有足够的权限写入注册表。请以管理员身份运行程序。");
                }

                myProgram = applications.CreateSubKey(dirname, RegistryKeyPermissionCheck.ReadWriteSubTree);

                myProgram.SetValue("DESCRIPTION", desc, RegistryValueKind.String);
                myProgram.SetValue("LOADCTRLS", 14, RegistryValueKind.DWord);
                myProgram.SetValue("LOADER", dllpath, RegistryValueKind.String);
                myProgram.SetValue("MANAGED", 1, RegistryValueKind.DWord);

                return true;
            }
            catch (UnauthorizedAccessException ex)
            {
                throw new Exception($"权限不足: {ex.Message}. 请以管理员身份运行程序。");
            }
            catch (Exception ex)
            {
                throw new Exception($"安装失败: {ex.Message}");
            }
            finally
            {
                myProgram?.Close();
                applications?.Close();
            }
        }
        /// <summary>
        /// 检查是否有写权限
        /// </summary>
        private bool HasWriteAccess(RegistryKey registryKey)
        {
            try
            {
                // 尝试创建一个测试项来验证写权限
                using (var testKey = registryKey.CreateSubKey("TestWriteAccess", RegistryKeyPermissionCheck.ReadWriteSubTree))
                {
                    if (testKey != null)
                    {
                        testKey.SetValue("Test", "TestValue", RegistryValueKind.String);
                        //registryKey.DeleteSubKey("TestWriteAccess", false);
                        registryKey.DeleteSubKey("TestWriteAccess");
                        return true;
                    }
                }
                return false;
            }
            catch
            {
                return false;
            }
        }


        public bool InstallRegistry(AddinModel model, AutoCadVersion autoCadVersion)
        {
            return InstallRegistry(model.Name, model.Description, model.Path, autoCadVersion);
        }
        /// <summary>
        /// 卸载注册表插件
        /// </summary>
        /// <param name="dirname">创建的文件名称</param>
        /// <param name="version">版本</param>
        private bool UnInstallRegistry(string dirname, AutoCadVersion autoCadVersion)
        {
            var app = GetApplication(autoCadVersion);
            string[] subkey = app.GetSubKeyNames();
            if (subkey.Contains(dirname))
            {
                app.DeleteSubKeyTree(dirname);
                return true;
            }
            return false;
        }

        public bool UnInstallRegistry(AddinModel model)
        {
            return UnInstallRegistry(model.Name, model.Version);
        }


        private RegistryKey GetLocalMactineByBitType(AutoCadVersion autoCadVersion)
        {
            if (autoCadVersion.BitVersion == BitType.bit32)
            {
                return Autodesk.AutoCAD.Runtime.Registry.LocalMachine;
            }
            else
            {
                return RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
            }
        }











        private RegistryKey GetApplication(AutoCadVersion autoCadVersion)
        {
            try
            {
                RegistryKey localMachine = GetLocalMactineByBitType(autoCadVersion);
                string applicationsPath = $@"SOFTWARE\{autoCadVersion.RegistryPath}\Applications";

                // 尝试以写权限打开，如果失败则尝试以读权限打开
                RegistryKey applications = localMachine.OpenSubKey(applicationsPath, true);

                if (applications == null)
                {
                    // 如果没有写权限，尝试创建或获取只读访问
                    applications = CreateOrOpenApplicationsKey(localMachine, applicationsPath);
                }

                return applications;
            }
            catch (SecurityException ex)
            {
                throw new UnauthorizedAccessException($"没有足够的权限访问注册表: {ex.Message}", ex);
            }
            catch (Exception ex)
            {
                throw new ApplicationException($"访问注册表时发生错误: {ex.Message}", ex);
            }
        }
        private RegistryKey CreateOrOpenApplicationsKey(RegistryKey parentKey, string keyPath)
        {
            try
            {
                // 尝试创建或打开具有写权限的注册表项
                return parentKey.CreateSubKey(keyPath, RegistryKeyPermissionCheck.ReadWriteSubTree);
            }
            catch (UnauthorizedAccessException)
            {
                // 如果创建失败，尝试以只读方式打开
                return parentKey.OpenSubKey(keyPath, false);
            }
            catch (SecurityException)
            {
                // 如果安全异常，尝试以只读方式打开
                return parentKey.OpenSubKey(keyPath, false);
            }
        }











        /// <summary>
        /// 获得所有插件
        /// </summary>
        /// <param name="version"></param>
        /// <returns></returns>
        public List<AddinModel> GetAllAddin(AutoCadVersion autoCadVersion)
        {
            List<AddinModel> addinModels = new List<AddinModel>();
            var app = GetApplication(autoCadVersion);
            string[] subkey = app.GetSubKeyNames();
            foreach (var name in subkey)
            {
                if (name == "AcadVBA" || name == "HelpBrowser")
                {
                    continue;
                }
                AddinModel addinModel = new AddinModel();
                addinModel.Name = name;
                //插件的文件夹
                var folder = app.OpenSubKey(name);
                addinModel.Description = folder.GetValue("DESCRIPTION")?.ToString();
                addinModel.Path = folder.GetValue("LOADER")?.ToString();
                addinModel.Version = autoCadVersion;
                addinModels.Add(addinModel);
            }
            return addinModels;
        }





    }
}